package com.youi.interceptor;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youi.exception.BusinessException;
import com.youi.util.DateUtil;
import com.youi.util.JedisUtils;
import com.youi.util.JsonUtil;
import com.youi.util.LogUtil;
import com.youi.util.MD5;

/**
 * 会话签名
 * @author erdong.Chan
 *
 */
public class SessionSignature {

	private static String secret="10086";//密钥
	
	
	/**
	 * 验证签名
	 * @param request
	 * @return
	 * @throws BusinessException 
	 */
	public static  boolean CheckSignature(HttpServletRequest request) throws BusinessException{
		SortedMap<String, Object> headerparameters=getHeaderAttribute(request);
		SortedMap<String, Object> bodyparameters=SessionSignature.getBodyAttribute(request);
		return CheckSignature(headerparameters, bodyparameters);
	}
	
	/**
	 * 验证签名
	 * @param headerparameters
	 * @param bodyparameters
	 * @return
	 * @throws BusinessException
	 */
	public static  boolean CheckSignature(SortedMap<String, Object> headerparameters,SortedMap<String, Object> bodyparameters) throws BusinessException{
		if (headerparameters!=null) {
			String sign=(String) headerparameters.get("sign");
			if (sign==null||sign.length()==0) {
				throw new BusinessException(-1,"缺少签名");
			}
			String timestamp=(String) headerparameters.get("timestamp");
			if (timestamp==null||timestamp.length()==0) {
				throw new BusinessException(-1,"缺少时间戳");
			}else {
				try {
					SimpleDateFormat simpdfyMdHms = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					Long timestampDate=simpdfyMdHms.parse(timestamp).getTime();
					Long nowtimestamp=new Date().getTime();
					Long second=((nowtimestamp-timestampDate)/1000);//获取秒数
					if (!(second>=-180&&second<180)) {
						//System.err.println(timestampDate);
						//System.err.println(nowtimestamp);
						throw new BusinessException(-1,"时间戳已过时");
					}
				} catch (ParseException e) {
					throw new BusinessException(-1,"时间戳格式错误");
				}
			}
			String nonce=(String) headerparameters.get("nonce");
			if (nonce==null||nonce.length()==0) {
				throw new BusinessException(-1,"缺少随机数");
			}else {
				if (JedisUtils.exists(nonce)) {
					throw new BusinessException(-1,"60秒内随机数不能重复");
				}else {
					JedisUtils.setObject(nonce, nonce, 60);
				}
			}
			String signstr=createSign(bodyparameters,timestamp,nonce);//"secret"  "secretKey"
			if (signstr==null||signstr.length()==0) {
				throw new BusinessException(-1,"生成签名错误");
			}
			if (sign.equals(signstr)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 获取请求体请求参数 并按key值排序
	 * @param request
	 * @return
	 */
	public  static SortedMap<String,Object>  getBodyAttribute(HttpServletRequest request){
		Enumeration enu=request.getParameterNames();  
		if (enu!=null) {
			System.err.println("getBodyAttribute======");
			LogUtil.Info("getBodyAttribute======");
			SortedMap<String, Object> parameters = new TreeMap<String, Object>();
			while(enu.hasMoreElements()){  
				String paraName=(String)enu.nextElement();
				String value=request.getParameter(paraName);
				if (value!=null&&value.length()>0) {
					parameters.put(paraName, value);
					//System.err.println(paraName+"="+value);
					//LogUtil.Info(paraName+"="+value);
				}
				//LogUtil.Info(paraName+": "+request.getParameter(paraName));
			}
			return parameters;
		}
		return null;
	}
	
	/**
	 * 获取json传参
	 * @param request
	 * @return
	 * @throws IOException 
	 * @throws UnsupportedEncodingException 
	 */
	public  static SortedMap<String,Object>  getJsonAttribute(HttpServletRequest request){
		try {
			SortedMap<String, Object> bodyparameters = new TreeMap<String, Object>();
			InputStreamReader reader=new InputStreamReader(request.getInputStream(),"UTF-8");
			StringBuffer sb=new StringBuffer();
			char [] buff=new char[1024];
			int length=0;
			while((length=reader.read(buff))!=-1){
				sb.append(new String(buff,0,length));
			}
			if (sb.length()>0) {
				JSONObject json = JSON.parseObject(sb.toString());
				for (String key : json.keySet()) {
					Object object=json.get(key);
					if (object instanceof Integer) {
						bodyparameters.put(key, (Integer)object);
					}else {
						bodyparameters.put(key, object);
					}
					request.setAttribute(key, object);
					//System.err.println(key+"="+object);
					//LogUtil.Info(key+"="+object);
				}
				return bodyparameters;
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
	
	/**
	 * 获取请求头请求参数 并按key值排序
	 * @param request
	 * @return
	 */
	public  static SortedMap<String,Object>  getHeaderAttribute(HttpServletRequest request){
		Enumeration enu=request.getHeaderNames();  
		if (enu!=null) {
			System.err.println("getHeaderAttribute======");
			LogUtil.Info("getHeaderAttribute======");
			SortedMap<String, Object> parameters = new TreeMap<String, Object>();
			while(enu.hasMoreElements()){  
				String paraName=(String)enu.nextElement();
				String value=request.getHeader(paraName);
				if (value!=null&&value.length()>0) {
					parameters.put(paraName, value);
					System.err.println(paraName+"="+value);
					//LogUtil.Info(paraName+"="+value);
				}
				//LogUtil.Info(paraName+": "+request.getParameter(paraName));
			}
			return parameters;
		}
		return null;
	}
	
	/**
	 * 定义签名，根据参数字段的ASCII码值进行排序 加密签名,故使用SortMap进行参数排序
	 * @param parameters
	 * @return
	 */
    private static String createSign(SortedMap<String,Object> parameters,String timestamp,String nonce){
        StringBuffer sb = new StringBuffer();
        if (parameters!=null&&parameters.size()>0) {
        	Set es = parameters.entrySet();
            Iterator it = es.iterator();
            while(it.hasNext()) {
                Map.Entry entry = (Map.Entry)it.next();
                String k = (String)entry.getKey();
                Object v = entry.getValue();
                if(null != v && !"".equals(v)
                        && !"sign".equals(k) && !"secretKey".equals(k)&& !"token".equals(k)) { //过滤参数
                    sb.append(k + "=" + v + "&");
                }
            }
		}
        sb.append("timestamp=" + timestamp+"&");//时间戳
        sb.append("nonce=" + nonce+"&");//随机数
        sb.append("secretKey=" + secret);//最后加密时添加商户密钥，由于secret值放在最后，所以不用添加到SortMap里面去，单独处理，编码方式采用UTF-8
        System.out.println("签名前数据为="+sb.toString());
        String sign = MD5.getMD5(sb.toString()).toUpperCase();
        System.out.println(sign);
        System.out.println("生成app支付签名结束");
        return sign;
    }
    
    public static void main(String[] args) {
    	SortedMap<String, Object> parameters = new TreeMap<String, Object>();
    	parameters.put("secretKey", "75 ed 3e ef f7 07 b7 ae e8 9d 50 54 64 76 fc 62");
    	parameters.put("deviceName", "BLE-LOCK-7E1E");
    	parameters.put("type", "1");
    	parameters.put("battery", "50");
    	parameters.put("mac", "7E:1E:DE:CC:BB:AA");
    	String timestamp="2019-04-23 18:19:04";
		System.out.println(createSign(parameters, timestamp,"25656"));
	}
}
